package com.yzh.openai.infrastructure.repository;

import com.yzh.openai.domain.order.model.aggregates.CreateOrderAggregate;
import com.yzh.openai.domain.order.model.entity.*;
import com.yzh.openai.domain.order.model.valobj.OrderStatusVO;
import com.yzh.openai.domain.order.model.valobj.PayStatusVO;
import com.yzh.openai.domain.order.model.valobj.PayTypeVO;
import com.yzh.openai.domain.order.repositoy.IOrderRepository;
import com.yzh.openai.domain.weixin.model.valobj.UserAccountConfigVO;
import com.yzh.openai.infrastructure.dao.OpenaiOrderMapper;
import com.yzh.openai.infrastructure.dao.OpenaiProductMapper;
import com.yzh.openai.infrastructure.dao.UserAccountMapper;
import com.yzh.openai.infrastructure.po.OpenaiOrderPO;
import com.yzh.openai.infrastructure.po.OpenaiProductPO;
import com.yzh.openai.infrastructure.po.UserAccountPO;
import com.yzh.openai.types.enums.ProductEnable;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Repository
public class OrderRepository implements IOrderRepository {
    @Resource
    private OpenaiOrderMapper orderMapper;
    @Resource
    private OpenaiProductMapper productMapper;
    @Resource
    private UserAccountMapper userAccountMapper;

    @Override
    public UnpaidOrderEntity queryUnpaidOrder(ShopCartEntity shopCartEntity) {
        OpenaiOrderPO openaiOrderPO = orderMapper.queryUnpaidOrder(
                OpenaiOrderPO.builder()
                        .openid(shopCartEntity.getOpenid())
                        .productId(shopCartEntity.getProductId())
                        .build());
        
        if (openaiOrderPO == null) return null;
        
        UnpaidOrderEntity unpaidOrderEntity = new UnpaidOrderEntity();
        unpaidOrderEntity.setOpenid(openaiOrderPO.getOpenid());
        unpaidOrderEntity.setOrderId(openaiOrderPO.getOrderId());
        unpaidOrderEntity.setTotalAmount(openaiOrderPO.getTotalAmount());
        unpaidOrderEntity.setProductName(openaiOrderPO.getProductName());
        unpaidOrderEntity.setPayUrl(openaiOrderPO.getPayUrl());
        unpaidOrderEntity.setPayStatus(PayStatusVO.get(openaiOrderPO.getPayStatus()));
        
        return unpaidOrderEntity;
    }

    @Override
    public ProductEntity queryProduct(Integer productId) {
        OpenaiProductPO productPO = productMapper.queryProduct(productId);
        ProductEntity productEntity = new ProductEntity();
        productEntity.setProductId(productPO.getProductId());
        productEntity.setProductName(productPO.getProductName());
        productEntity.setProductDesc(productPO.getProductDesc());
        productEntity.setQuota(productPO.getQuota());
        productEntity.setPrice(productPO.getPrice());
        productEntity.setProductEnable(ProductEnable.get(productPO.getIsEnabled()));
        return productEntity;
    }

    @Override
    public void saveOrder(CreateOrderAggregate aggregate) {
        // 1. 保存订单
        OpenaiOrderPO orderPO = new OpenaiOrderPO();
        OrderEntity order = aggregate.getOrder();
        ProductEntity product = aggregate.getProduct();
        orderPO.setOpenid(aggregate.getOpenid());
        orderPO.setProductId(product.getProductId());
        orderPO.setProductName(product.getProductName());
        orderPO.setProductQuota(product.getQuota());
        orderPO.setOrderId(order.getOrderId());
        orderPO.setOrderTime(order.getOrderTime());
        orderPO.setOrderStatus(order.getOrderStatus().getCode());
        orderPO.setTotalAmount(order.getTotalAmount());
        orderPO.setPayType(order.getPayTypeVO().getCode());
        orderPO.setPayStatus(PayStatusVO.WAIT.getCode());
        
        orderMapper.insert(orderPO);
    }

    @Override
    public void updateOrderPayInfo(PayOrderEntity payOrderEntity) {
        OpenaiOrderPO orderPO = OpenaiOrderPO.builder()
                .openid(payOrderEntity.getOpenid())
                .orderId(payOrderEntity.getOrderId())
                .payUrl(payOrderEntity.getPayUrl())
                .payStatus(payOrderEntity.getPayStatus().getCode())
                .build();
        orderMapper.updateOrderPayInfo(orderPO);
    }

    @Override
    public boolean changeOrderPaySuccess(String orderId, String transactionId, BigDecimal totalAmount, Date payTime) {
        OpenaiOrderPO orderPO = OpenaiOrderPO.builder()
                .orderId(orderId)
                .transactionId(transactionId)
                .totalAmount(totalAmount)
                .payTime(payTime)
                .build();
        int count = orderMapper.changeOrderPaySuccess(orderPO);
        return count == 1;
    }

    @Override
    public CreateOrderAggregate queryOrder(String orderId) {
        OpenaiOrderPO openaiOrderPO = orderMapper.queryOrder(orderId);
        CreateOrderAggregate createOrderAggregate = new CreateOrderAggregate();
        createOrderAggregate.setOpenid(openaiOrderPO.getOpenid());
        createOrderAggregate.setOrder(
                OrderEntity.builder()
                        .orderId(openaiOrderPO.getOrderId())
                        .orderTime(openaiOrderPO.getOrderTime())
                        .orderStatus(OrderStatusVO.get(openaiOrderPO.getOrderStatus()))
                        .totalAmount(openaiOrderPO.getTotalAmount())
                        .payTypeVO(PayTypeVO.get(openaiOrderPO.getPayType()))
                        .build()
        );
        createOrderAggregate.setProduct(
                ProductEntity.builder()
                        .productId(openaiOrderPO.getProductId())
                        .productName(openaiOrderPO.getProductName())
                        .quota(openaiOrderPO.getProductQuota())
                        .build()
        );
        return createOrderAggregate;
    }

    @Override
    @Transactional(rollbackFor = Exception.class, timeout = 350, propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT)
    public void deliverGoods(String orderId) {
        OpenaiOrderPO openaiOrderPO = orderMapper.queryOrder(orderId);
        //1.变更发货状态
        int update = orderMapper.updateOrderStatusDeliverGoods(orderId);
        if (update != 1) throw new RuntimeException("updateOrderStatusDeliverGoods Error");

        //2.账户额度变更
        UserAccountPO userAccountPO = userAccountMapper.queryUserAccount(openaiOrderPO.getOpenid());
        UserAccountPO request = UserAccountPO.builder()
                .openid(openaiOrderPO.getOpenid())
                .totalQuota(openaiOrderPO.getProductQuota())
                .surplusQuota(openaiOrderPO.getProductQuota())
                .build();
        //存在用户
        if (userAccountPO != null) {
            int addQuota = userAccountMapper.addAccountQuota(request);
            if (addQuota != 1) throw new RuntimeException("addAccountQuota Error");
        } else {
            //新增用户
            request = new UserAccountPO().builder()
                    .openid(openaiOrderPO.getOpenid())
                    .totalQuota(UserAccountConfigVO.totalQuota + openaiOrderPO.getProductQuota())
                    .surplusQuota(UserAccountConfigVO.surplusQuota + openaiOrderPO.getProductQuota())
                    .modelTypes(UserAccountConfigVO.modelTypes)
                    .status(UserAccountConfigVO.status)
                    .build();
            userAccountMapper.insertUserAccount(request);
        }
    }

    @Override
    public List<String> queryReplenishmentOrder() {
        return orderMapper.queryReplenishmentOrder();
    }

    @Override
    public List<String> queryNoPayNotifyOrderList() {
        return orderMapper.queryNoPayNotifyOrderList();
    }
    @Override
    public String queryNoPayNotifyOrder() {
        return orderMapper.queryNoPayNotifyOrder();
    }

    @Override
    public List<String> queryTimeoutCloseOrderList() {
        return orderMapper.queryTimeoutCloseOrderList();
    }

    @Override
    public boolean changeOrderClose(String orderId) {
        return orderMapper.changeOrderClose(orderId);
    }

    @Override
    public List<ProductEntity> queryProductList() {
        List<OpenaiProductPO> productPOList = productMapper.queryProductList();
        List<ProductEntity> productEntityList = new ArrayList<>();
        for (OpenaiProductPO productPO : productPOList) {
            ProductEntity productEntity = new ProductEntity();
            productEntity.setProductId(productPO.getProductId());
            productEntity.setProductName(productPO.getProductName());
            productEntity.setProductDesc(productPO.getProductDesc());
            productEntity.setQuota(productPO.getQuota());
            productEntity.setPrice(productPO.getPrice());
            productEntityList.add(productEntity);
        }
        return productEntityList;
    }
}
